package joc.systemtest.methodcallsequence;

import joc.CallSequenceProvider;
import joc.JOCCallSequence;
import joc.JOCEnabled;
import joc.systemtest.methodcallsequence.MethodCallSequenceWithInterfaceOrSuperclass.CallSequenceInterface.DummyClassCallSequenceProvider;
import joc.systemtest.methodcallsequence.MethodCallSequenceWithInterfaceOrSuperclass.DummyClassWithOwnSequence.DummyClassWithOwnSequenceCallSequenceProvider;

import org.junit.Before;
import org.junit.Test;

public class MethodCallSequenceWithInterfaceOrSuperclass {
	private DummyClass terminal;
	private DummyClassWithOwnSequence ownSequence;

	@Before
	public void before() {
		terminal = new DummyClass();
		ownSequence = new DummyClassWithOwnSequence();
	}

	@Test
	public void testEasySequence() {
		terminal.firstMethod();
		terminal.secondMethod();
	}

	@Test(expected = AssertionError.class)
	public void testEasySequenceFailingWithFirst() {
		terminal.secondMethod();
	}

	@Test(expected = AssertionError.class)
	public void testEasySequenceFailingWithSecond() {
		terminal.firstMethod();
		terminal.firstMethod();
	}

	@Test
	public void testOwnSequenceSuccess() {
		ownSequence.firstMethod();
		ownSequence.thirdMethod();
		ownSequence.secondMethod();
	}

	@Test(expected = AssertionError.class)
	public void testOwnSequenceFailingWithOwnSequence() {
		ownSequence.firstMethod();
		ownSequence.secondMethod();
	}

	@Test(expected = AssertionError.class)
	public void testOwnSequenceFailingWithInterfaceSequence() {
		ownSequence.firstMethod();
		ownSequence.fourthMethod();
	}

	@JOCEnabled
	public static class DummyClass implements CallSequenceInterface {
		@Override
		public void firstMethod() {
		}

		@Override
		public void secondMethod() {
		}

		@Override
		public void thirdMethod() {
		}

		@Override
		public void fourthMethod() {
		}

	}

	@JOCEnabled
	@JOCCallSequence(DummyClassWithOwnSequenceCallSequenceProvider.class)
	public static class DummyClassWithOwnSequence implements CallSequenceInterface {
		@Override
		public void firstMethod() {
		}

		@Override
		public void secondMethod() {
		}

		@Override
		public void thirdMethod() {
		}

		@Override
		public void fourthMethod() {
		}

		public static class DummyClassWithOwnSequenceCallSequenceProvider extends
				CallSequenceProvider<DummyClassWithOwnSequence> {

			@Override
			public void callSequence(DummyClassWithOwnSequence arg0) {
				call().firstMethod();
				before().thirdMethod();
				before().secondMethod();
				allowAnywhereWithinThisSequence().fourthMethod();
			}
		}
	}

	@JOCEnabled
	@JOCCallSequence(DummyClassCallSequenceProvider.class)
	public interface CallSequenceInterface {
		void firstMethod();

		void secondMethod();

		void thirdMethod();

		void fourthMethod();

		public static class DummyClassCallSequenceProvider extends CallSequenceProvider<DummyClass> {
			@Override
			public void callSequence(DummyClass target) {
				call().firstMethod();
				before().secondMethod();
				allowAnywhereWithinThisSequence().thirdMethod();
			}
		}
	}

}
